package com.jimmy.medical.service.impl;

import com.jimmy.medical.base.impl.JpaSpecificationServiceImpl;
import com.jimmy.medical.common.StringUtils;
import com.jimmy.medical.entity.FlowOrder;
import com.jimmy.medical.entity.Hospital;
import com.jimmy.medical.entity.User;
import com.jimmy.medical.enums.RoleTypeEnum;
import com.jimmy.medical.model.UserStat;
import com.jimmy.medical.service.IFileService;
import com.jimmy.medical.service.IFlowOrderService;
import com.jimmy.medical.service.IUserService;
import com.jimmy.medical.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl extends JpaSpecificationServiceImpl<UserRepository, UserRepository, User, Long>
        implements IUserService {

    private static Long oneDayMills = 24 * 60 * 60 * 1000L;

    private static DecimalFormat decimalFormat = new DecimalFormat("0.00");

    @Autowired
    private UserRepository repository;
    @Autowired
    private IFileService fileService;
    @Autowired
    @Qualifier("flowOrderService")
    private IFlowOrderService flowOrderService;

    public User checkUser(String username, String password) {
        return repository.findByUsernameAndPassword(username, password);
    }

    public Page<UserStat> findUserWithStat(Pageable pageable, String city, Long hospital, String realName) {
        Page<User> userPage = findAll(pageable, city, hospital, realName);
        List<UserStat> userStatList = new ArrayList<UserStat>();
        for(User user : userPage.getContent()) {
            UserStat stat = new UserStat();
            //
            List<FlowOrder> userTodoList = flowOrderService.getUserTask(user.getId());
            int todoToday = 0;
            int todoAll = 0;
            for(FlowOrder o : userTodoList) {
                todoAll ++;
                if(flowOrderService.getCountDownInternal(o) > oneDayMills) {
                    todoToday ++;
                }
            }
            stat.setUserId(user.getId());
            stat.setUserRealName(user.getRealname());
            stat.setUserMobile(user.getMobile());
            stat.setTodoAll(todoAll);
            stat.setTodoToday(todoToday);
            if(user.getPhoto() != null && StringUtils.isNotBlank(user.getPhoto().getFileUrl())) {
                stat.setPhoto(fileService.getDownloadUrl() + user.getPhoto().getFileUrl());
            }
            if(user.getFlowOrderCount() == null || user.getFlowOrderCount() == 0) {
                stat.setCancelPercent("0.00%");
                stat.setOverTimePercent("0.00%");
            } else if(user.getCancelFlowOrderCount() == null) {
                stat.setCancelPercent("0.00%");
            } else if(user.getOverTimeCount() == null) {
                stat.setOverTimePercent("0.00%");
            } else {
                stat.setCancelPercent(decimalFormat.format(user.getCancelFlowOrderCount()*100/user.getFlowOrderCount()) + "%");
                stat.setOverTimePercent(decimalFormat.format(user.getOverTimeCount()*100/user.getFlowOrderCount()) + "%");
            }

            userStatList.add(stat);
        }

        Page<UserStat> statPage = new PageImpl<UserStat>(userStatList, pageable, userPage.getTotalElements());
        return statPage;
    }

    @Override
    public Page<User> findAll(Pageable pageable, final String city, final Long hospital, final String realName) {
        return this.findAll(new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Join<User, Hospital> hospitalJoin = root.join("hospital", JoinType.LEFT);

                Path<String> cityPath = root.get("cityList");
                Path<String> realNamePath = root.get("realname");
                Path<Long> hospitalPath = hospitalJoin.get("id");
                Path<Long> rolePath = root.get("roleId");

                ArrayList<Predicate> list = new ArrayList<Predicate>();
                list.add(criteriaBuilder.equal(rolePath, RoleTypeEnum.WAITING_ROOM.getKey()));

                if(hospital != null) {
                    list.add(criteriaBuilder.and(criteriaBuilder.equal(hospitalPath, hospital)));
                } else if(StringUtils.isNotBlank(city)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.like(cityPath, "%" + city + "%")));
                }

                if(StringUtils.isNotBlank(realName)) {
                    list.add(criteriaBuilder.and(criteriaBuilder.like(realNamePath, realName + "%")));
                }

                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        }, pageable);
    }
}